/*
 * Saphre - Suffix Arrays for Phrase Extraction
 * Copyright (C) 2013 
 * Dale Gerdemann Tübingen, Germany 
 * Niko Schenk Frankfurt am Main, Germany
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
package collectors.impl;

import collectors.api.Collector2;
import java.util.Map;
import util.Interval;
import saphre.core.SuffixArray;
import saphre.core.Store;
import util.tokenization_io.BoundarySymbols;
import collectors.impl.visitors.CollectTraversal;
import java.io.PrintWriter;
import util.sorting.Multiset;
import util.sorting.RadixQSort;

import java.util.Set;
import java.util.TreeSet;
import saphre.commands.CmdGappyParameters;
import util.statistics.Ngram;
import util.sedgewick.StdRandom;

/**
 * Class which simulates lcp-interval tree traversal to collect GAPPY PHRASES.
 * It implements the Collector2 interface.
 *
 * Collect the LEFT AND INITIAL part of a phrase.
 * 
 * 
 * @authors Dale Gerdemann, Niko Schenk
 */
public class GappyPhrasesInitialPartPrintCollector implements Collector2 {

    private Store store;
    private BoundarySymbols tc;
    private SuffixArray pa;
    private Interval top;
    private SuffixArray sa;
    private CmdGappyParameters gappyParameters;
    private Map<String, Ngram> ngramMap;
    private PrintWriter gW;

    /**
     * 
     * @param store
     * @param pa
     * @param top
     * @param sa
     * @param gappyParameters
     * @param ngramMap 
     */
    public GappyPhrasesInitialPartPrintCollector(Store store, SuffixArray pa, Interval top, SuffixArray sa,
            CmdGappyParameters gappyParameters, Map<String, Ngram> ngramMap, PrintWriter gW) {

        this.store = store;
        tc = store.getTC();
        this.pa = pa;
        this.top = top;
        this.sa = sa;

        this.gappyParameters = gappyParameters;
        this.ngramMap = ngramMap;
        this.gW = gW;
    }


    /**
     *
     * @param pa
     */
    public void addPrefixArray(SuffixArray pa) {
    }

    /**
     *
     * @param inter
     * @param parentLcp
     * @param lcp
     * @param depth
     */
    @Override
    public void preAdd(Interval inter, int parentLcp, int lcp,
            int depth) {
    }

    /**
     *
     * @param inter
     * @param parentLcp
     * @param lcp
     * @param depth
     * @param docDist
     * @param rightContext
     */
    @Override
    public void add(Interval inter, int parentLcp, int lcp,
            int depth,
            Multiset docDist, Multiset rightContext) {
        if (rightContext.size() == 1) {
            return;
        }
        int incr = lcp - parentLcp;
        int len = parentLcp + incr;
        int loc = pa.getSuftab()[inter.lb()];
        Set<Integer> rightStart = new TreeSet<Integer>();
        Set<Integer> rightSpan = new TreeSet<Integer>();
        int[] rightSpanArray;
        Set<Integer> leftSpan = new TreeSet<Integer>();
        int[] leftSpanArray;
        SuffixArray sa2 = null;
        Interval top2 = null;

        for (int i = inter.lb(); i <= inter.rb(); i++) {
            int loci = pa.getSuftab()[i];
            boolean reject = false;
            int minGap = gappyParameters.getMinGap();
            for (int j = loci + 1; j < loci + 1 + minGap; j++) {
                // Fixed.
                if (j == store.text.length) {
                    //reject = true;
                    break;
                }
                if (tc.userSentinel(store.text[j])) {
                    reject = true;
                    break;
                }
            }
            if (!reject) {
                rightStart.add(loci + 1);
                int maxGap = gappyParameters.getMaxGap();
                for (int j = loci + 1 + minGap;
                        j <= Math.min(top.rb() - maxGap, loci + 1 + maxGap); j++) {
                    rightSpan.add(j);
                }
            }
            if (rightSpan.isEmpty()) {
                return;
            }
        }
        rightSpanArray = new int[rightSpan.size() + 1];
        int j = 1;
        for (int locj : rightSpan) {
            rightSpanArray[j++] = locj;
        }
        leftSpanArray = new int[leftSpan.size() + 1];
        j = 1;
        for (int locj : leftSpan) {
            leftSpanArray[j++] = locj;
        }
        if (rightSpanArray.length > 1) {
            RadixQSort rv = new RadixQSort(store.text);
            StdRandom.shuffle(rightSpanArray, 1, rightSpanArray.length - 1);
            rv.sort(rightSpanArray, 1, rightSpanArray.length - 1, 0);
            int[] lcptab = SuffixArray.getLcptab(rightSpanArray, store.text, store.getTC());
            sa2 = new SuffixArray(pa, rightSpanArray, lcptab);
            top2 = new Interval(1, rightSpanArray.length - 1);
        }
        int[] leftPart = store.toArray(loc - len + 1, loc + 1);


        // Get the right part !
        GappyPhrasesRightPartPrintCollector collect = 
                new GappyPhrasesRightPartPrintCollector(
                leftPart, rightStart,
                store, sa2, top, sa, pa,
                gappyParameters, gW, ngramMap);

        // Traverse lcp-interval tree again to find the relevant stuff.
        CollectTraversal p =
                new CollectTraversal(store, sa2, collect, top2);
        p.traverse();
        
        if (collect.foundRightPart()) {
            System.out.println();
        }

    }

    /**
     *
     * @param inter
     * @param lcp
     * @param depth
     * @param docDist
     * @param rightContext
     */
    @Override
    public void addTrivial(Interval inter, int lcp, int depth,
            Multiset docDist, Multiset rightContext) {
    }
}
